/*LICENSE_BEGIN
 * ******************************************************************
 * All original parts of SoccerScope2003 have copyright (2003) by
 * Team YowAI, represented by Mr. Shuhei Shiota
 * The Department of Creative Informatics
 * The Graduate School of Information Science and Technology
 * The University of Tokyo
 * 
 * Additional classes (except libraries in /lib) were developed by 
 * the Dainamite Robocup-Team of the DAI-Labor, TU-Berlin 
 * (www.dai-labor.de)
 * 
 * Extended/new classes/packages are:
 *   soccerscope.analyzer.LogfileAnalyzer
 *   soccerscope.daistatistic.*
 *   soccerscope.daistatistic.charts.*
 *   soccerscope.daistatistic.tools.*
 *   soccerscope.db.*
 *   soccerscope.dialog.*
 *   soccerscope.model.PlayerWorldModel
 *   soccerscope.model.SimplePlayer
 *   soccerscope.net.AgentConnector
 *   soccerscope.training.*
 *   soccerscope.training.conditions.*
 * ******************************************************************
LICENSE_END*/
package soccerscope.daistatistic.charts;

import robocup.component.PConf;
import robocup.component.SConf;
import soccerscope.daistatistic.Register;
import soccerscope.daistatistic.StatisticDialog;
import soccerscope.model.ClientScene;
import soccerscope.model.Player;
import soccerscope.model.PlayerWorldModel;
import soccerscope.model.WorldModel;
import soccerscope.net.AgentConnector;

/**
 * this class calculates and/or gets the wanted values
 * 
 */
public class DataHistory {

    // value if no value can be calculated
    public final static double gap_value = 0.0;

    // a new sconf, needed for global values like field langth
    static SConf sConf = SConf.getInstance();

    static PConf pConf = new PConf();

    public static final int Mode_StaminaOfPlayer = 101;

    public static final int Mode_ViewAngleOfPlayer = 102;

    public static final int Mode_BodyAngleOfPlayer = 103;

    public static final int Mode_NeckAngleOfPlayer = 104;

    public static final int Mode_ViewQualityOfPlayer = 105;

    public static final int Mode_BallPossession = 110;

    public static final int Mode_AbsPostitionDifferenceOfPlayer = 201;

    public static final int Mode_XPostitionDifferenceOfPlayer = 202;

    public static final int Mode_YPostitionDifferenceOfPlayer = 203;

    public static final int Mode_SpeedDifference = 204;

    public static final int Mode_SpeedXDiff = 205;

    public static final int Mode_SpeedYDiff = 206;

    public static final int Mode_NeckAngleDifference = 220;

    public static final int Mode_BodyAngleDifference = 221;

    public static final int Mode_BallPositionDiff = 250;

    public static final int Mode_BallXPosDiff = 251;

    public static final int Mode_BallYPosDiff = 252;

    public static final int Mode_BallSpeedDifference = 253;

    public static final int Mode_BallSpeedXDiff = 254;

    public static final int Mode_BallSpeedYDiff = 255;

    public static final int Mode_BallIntercept = 256;

    public static final int Mode_BallInterceptX = 257;

    public static final int Mode_BallInterceptY = 258;

    public static final int Mode_BallSpeedTMinus1 = 259;

    public static final int Mode_DistanceBallToGoalWM = 260;

    public static final int Mode_DistanceBallToGoalMonitor = 261;

    public static final int Mode_Pass = 302;

    public static final int Mode_DistanceToEnemyMonitor = 303;

    public static final int Mode_DistanceToTeamMonitor = 304;

    public static final int Mode_Holes = 401;

    public static final int Mode_PositionOfOpponents = 500;

    public static final int Mode_PositionOfTeammates = 501;

    public static final int Mode_SpeedOfOpponents = 502;

    public static final int Mode_SpeedOfTeammates = 503;

    // the teammate or opponent player number, used by some special modes
    static int secondPlayer = 1;

    /**
     * calls perform, used for modes with an opponent or temmate
     * 
     * @param int
     *            playerNumber, getting values of that player
     * @param int
     *            mode, wanted value type
     * @param int
     *            secondPlayerNumber, number of teammate or opponent
     */
    public static double[] performWithSecondPlayer(int number, int mode,
            int secondPlayerNumber) {
        secondPlayer = secondPlayerNumber;
        return perform(number, mode);
    }

    /**
     * 
     * gets an array with all values depends of the cycles and mode double[x]
     * value at cycle x
     * 
     * @param int
     *            playerNumber, getting values of that player
     * @param int
     *            mode, wanted value type
     */
public static double[] perform(int number, int mode) {
        // create an
        // array with the length of the actual cycle/game length count
        double[] values = getDoubleArrayWithActualCycleLength();

        // allocate client scene
        ClientScene scene = new ClientScene();

        int lastSceneTime = -9999;

        // all other chart modes
        for (int i = 0; i < WorldModel.sceneSet.size() - 1; i++) { // for each
            // scene...

            if (scene.time != WorldModel.sceneSet.elementAt(i + 1).time) {

                scene = WorldModel.sceneSet.elementAt(i); // get actual scene
                // of interest

                if (scene.time < values.length) { // and if scene time meets
                    // cycle intervall...

                    // fill array with needed values
                    Player player = scene.player[number - 1];
                    PlayerWorldModel pwm = player.getWorldModel();
                    int teamMemberCount = 11;

                    // charts with soccerscope attributes only
                    if (mode == Mode_StaminaOfPlayer)
                        // set stamina
                        values[scene.time] = scene.player[number - 1].stamina;
                    if (mode == Mode_ViewAngleOfPlayer)
                        // set visible angle
                        values[scene.time] = scene.player[number - 1].angleVisible;
                    if (mode == Mode_BodyAngleOfPlayer)
                        // set body angle
                        values[scene.time] = scene.player[number - 1].angle;
                    if (mode == Mode_NeckAngleOfPlayer)
                        // set neck angle
                        values[scene.time] = scene.player[number - 1].angleNeck;
                    if (mode == Mode_ViewQualityOfPlayer)
                        // set view quality
                        values[scene.time] = scene.player[number - 1].viewQuality;

                    // charts with need soccerscope and dai history/world model
                    // attributes
                    if (mode == Mode_BallPossession) {

                        // set radius defined as ball possession
                        double radius = pConf.KICKABLE_MARGIN + pConf.PLAYER_SIZE;

                        values[scene.time] = 0;
                        int playerIndex = -1;

                        // search player with ball
                        for (int j = 0; j < scene.player.length; j++) {
                            if ((scene.player[j].pos.x - scene.ball.pos.x) < radius
                                    && (scene.player[j].pos.x - scene.ball.pos.x) > -radius
                                    && (scene.player[j].pos.y - scene.ball.pos.y) < radius
                                    && (scene.player[j].pos.y - scene.ball.pos.y) > -radius) {
                                if (playerIndex == -1)
                                    playerIndex = j;
                                else {
                                    // two player in radius distance to ball
                                    if (Math
                                            .abs(scene.player[j].pos.x - scene.ball.pos.x) < Math
                                            .abs(scene.player[playerIndex].pos.x
                                                    - scene.ball.pos.x)
                                            && Math.abs(scene.player[j].pos.y
                                                    - scene.ball.pos.y) < Math
                                                    .abs(scene.player[playerIndex].pos.y
                                                            - scene.ball.pos.y)) // set
                                        // possession
                                        // to
                                        // player
                                        // with
                                        // smallest
                                        // distance
                                        playerIndex = j;
                                }
                            }
                        }
                        if (playerIndex > -1)
                            // set possession to left or right team

                            if (playerIndex > (teamMemberCount - 1))
                                values[scene.time] = -1;
                            else
                                values[scene.time] = 1;
                    }

                    if (mode == Mode_Pass) {
                        if (pwm == null || !pwm.doneAPass) {
                            values[scene.time] = 0;
                            // System.out.println("No Pass in cycle " +
                            // scene.time);
                        } else {
                            // System.out.println("Pass in cycle " + scene.time
                            // + " / scene " + i);

                            // get scene and player with next ball contact
                            int indexWithNextContact = getIndexWithNextBallContact(i + 1);
                            int nextPlayerWithBall = wichPlayerHasBallAtSceneTime(indexWithNextContact);

                            // System.out.println("Next Player with Ball " +
                            // nextPlayerWithBall + " at cycle " +
                            // indexWithNextContact);

                            // pass should go to player with number paaToPlayer
                            values[scene.time] = pwm.passToPlayer;

                            // if a next ball contact exist
                            if (indexWithNextContact > 0) {

                                // if the next ball contact is in next cycle or
                                // later
                                // (not only in next scene)
                                if (WorldModel.sceneSet.elementAt(indexWithNextContact).time > scene.time) {

                                    int help = scene.time;

                                    // fo all scenes till next ball contact
                                    // /indexWithNextContact
                                    for (int j = i; j < indexWithNextContact; j++) {

                                        // if the cycle number of the next scene
                                        // != actual cycle number
                                        if (WorldModel.sceneSet.elementAt(j).time != WorldModel.sceneSet
                                                .elementAt(j + 1).time) {

                                            // store ball pass destination
                                            values[help] = pwm.passToPlayer;
                                            help++;
                                        }
                                    }
                                }

                                // if nextPlayerWithBall is an opponent make his
                                // number negative
                                if (nextPlayerWithBall > teamMemberCount)
                                    nextPlayerWithBall = -(nextPlayerWithBall - teamMemberCount);

                                // store player number of reciever at cycle with
                                // next contact
                                values[WorldModel.sceneSet
                                        .elementAt(indexWithNextContact).time] = nextPlayerWithBall;
                            }

                            // if (indexWithNextContact > i)
                            // i = indexWithNextContact + 1;
                        }
                    }

                    if (mode == Mode_PositionOfOpponents) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            double a = (scene.player[secondPlayer - 1 + teamMemberCount].pos.y)
                                    - pwm.opponents[secondPlayer - 1].positionX;

                            double b = (scene.player[secondPlayer - 1 + teamMemberCount].pos.x)
                                    - pwm.opponents[secondPlayer - 1].positionY;

                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        }
                    }
                    if (mode == Mode_PositionOfTeammates) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            double a = (scene.player[secondPlayer - 1].pos.y)
                                    - pwm.teammates[secondPlayer - 1].positionX;
    
                            double b = (scene.player[secondPlayer - 1].pos.x)
                                    - pwm.teammates[secondPlayer - 1].positionY;
    
                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        }
                    }
                    if (mode == Mode_SpeedOfOpponents) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            double a = (scene.player[secondPlayer - 1
                                    + Register.getNumberOfPlayersLeftTeam()].vel.y)
                                    - pwm.opponents[secondPlayer - 1].speedX;
    
                            double b = (scene.player[secondPlayer - 1
                                    + Register.getNumberOfPlayersLeftTeam()].vel.x)
                                    - pwm.opponents[secondPlayer - 1].speedY;
    
                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        }
                    }
                    if (mode == Mode_SpeedOfTeammates) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            double a = (scene.player[secondPlayer - 1].vel.y)
                                    - pwm.teammates[secondPlayer - 1].speedX;
    
                            double b = (scene.player[secondPlayer - 1].vel.x)
                                    - pwm.teammates[secondPlayer - 1].speedY;
    
                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        }
                    }

                    if (mode == Mode_AbsPostitionDifferenceOfPlayer) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            double a = (scene.player[number - 1].pos.y) - pwm.positionX;
    
                            double b = (scene.player[number - 1].pos.x) - pwm.positionY;
    
                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        }
                    }
                    if (mode == Mode_XPostitionDifferenceOfPlayer) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = scene.player[number - 1].pos.y
                                    - pwm.positionX;
                        }
                    }
                    if (mode == Mode_YPostitionDifferenceOfPlayer) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = scene.player[number - 1].pos.x
                                    - pwm.positionY;
                        }
                    }
                    if (mode == Mode_SpeedDifference) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            double a = (scene.player[number - 1].vel.y) - pwm.speedX;
    
                            double b = (scene.player[number - 1].vel.x) - pwm.speedY;
    
                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        }
                    }
                    if (mode == Mode_SpeedXDiff) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = scene.player[number - 1].vel.y - pwm.speedX;
                        }
                    }
                    if (mode == Mode_SpeedYDiff) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = scene.player[number - 1].vel.x - pwm.speedY;
                        }
                    }

                    if (mode == Mode_NeckAngleDifference) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = scene.player[number - 1].angleNeck
                                    - pwm.neckAngle;
                        }
                    }
                    if (mode == Mode_BodyAngleDifference) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = scene.player[number - 1].angle
                                    - pwm.bodyAngle;
                        }
                    }

                    if (mode == Mode_BallPositionDiff) {
                        if (checkBallDistance(number, scene)) {
                            double a = (scene.ball.pos.y) - pwm.ballPositionX;

                            double b = (scene.ball.pos.x) - pwm.ballPositionY;

                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallXPosDiff) {
                        if (pwm != null && checkBallDistance(number, scene)) {
                            values[scene.time] = scene.ball.pos.y - pwm.ballPositionX
                                    - scene.player[number - 1].pos.y + pwm.positionX;
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallYPosDiff) {
                        if (pwm != null && checkBallDistance(number, scene)) {
                            values[scene.time] = scene.ball.pos.x - pwm.ballPositionY
                                    - scene.player[number - 1].pos.x + pwm.positionY;
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallSpeedDifference) {
                        if (checkBallDistance(number, scene)) {
                            double a = (scene.ball.vel.y) - pwm.ballSpeedX;
                            double b = (scene.ball.vel.x) - pwm.ballSpeedY;
                            values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallSpeedXDiff) {
                        if (checkBallDistance(number, scene)) {
                            values[scene.time] = scene.ball.vel.y - pwm.ballSpeedX;
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallSpeedYDiff) {
                        if (checkBallDistance(number, scene)) {
                            values[scene.time] = scene.ball.vel.x - pwm.ballSpeedY;
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallIntercept) {
                        if (checkBallDistance(number, scene) && scene.time > 0) {
                            PlayerWorldModel pwmLastScene = WorldModel.getSceneSet()
                                    .elementAt(scene.time - 1).player[number - 1]
                                    .getWorldModel();

                            if (pwmLastScene == null) {
                                values[scene.time] = 0;
                            } else {
                                double a1 = pwm.ballInterceptX;
                                double a2 = pwmLastScene.ballInterceptX;
                                double b1 = pwm.ballInterceptY;
                                double b2 = pwmLastScene.ballInterceptY;
    
                                if (a2 == -9999 || b2 == -9999) {
                                    for (int j = scene.time - 2; j > 0; j--) {
                                        a2 = pwmLastScene.ballInterceptX;
                                        b2 = pwmLastScene.ballInterceptY;
                                        if (a2 != -9999 && b2 != -9999)
                                            break;
                                    }
                                }
    
                                double a = a1 - a2;
                                double b = b1 - b2;
    
                                values[scene.time] = java.lang.Math.sqrt(a * a + b * b);
                                // System.out.println("Ball Intercept Diff " +
                                // java.lang.Math.sqrt(a * a + b * b) +
                                // " in Scene.Time/cycle " + scene.time + "/" +
                                // DaiWorldModelHistory.getCycle(scene.time).cycleNumber);
                            }
                        } else
                            values[scene.time] = gap_value;
                    }

                    if (mode == Mode_BallInterceptX) {
                        if (checkBallDistance(number, scene) && scene.time > 0) {
                            PlayerWorldModel pwmLastScene = WorldModel.getSceneSet()
                                    .elementAt(scene.time - 1).player[number - 1]
                                    .getWorldModel();

                            if (pwmLastScene == null) {
                                values[scene.time] = 0;
                            } else {
                                double a1 = pwm.ballInterceptX;
                                double a2 = pwmLastScene.ballInterceptX;
                                if (a2 == -9999) {
                                    for (int j = scene.time - 2; j > 0; j--) {
                                        a2 = pwmLastScene.ballInterceptX;
                                        if (a2 != -9999)
                                            break;
                                    }
                                }
                                values[scene.time] = a1 - a2;
                            }
                        } else {
                            values[scene.time] = gap_value;
                        }
                    }

                    if (mode == Mode_BallInterceptY) {
                        if (checkBallDistance(number, scene) && scene.time > 0) {
                            PlayerWorldModel pwmLastScene = WorldModel.getSceneSet()
                                    .elementAt(scene.time - 1).player[number - 1]
                                    .getWorldModel();

                            if (pwmLastScene == null) {
                                values[scene.time] = 0;
                            } else {
                                double b1 = pwm.ballInterceptY;
                                double b2 = pwmLastScene.ballInterceptY;
                                if (b2 == -9999) {
                                    for (int j = scene.time - 2; j > 0; j--) {
                                        b2 = pwmLastScene.ballInterceptX;
                                        if (b2 != -9999)
                                            break;
                                    }
                                }
                                values[scene.time] = b1 - b2;
                            }
                        } else {
                            values[scene.time] = gap_value;
                        }
                    }

                    if (mode == Mode_Holes) {
                        /*
                         * if (scene.time > 0) { values[scene.time] =
                         * DaiWorldModelHistory
                         * .getCycle(scene.time).players[number - 1].holes; }
                         * else values[0] = gap_value;;
                         */

                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = pwm.holes;
                        }

                    }

                    if (mode == Mode_DistanceBallToGoalWM) {
                        if (pwm == null) {
                            values[scene.time] = 0;
                        } else {
                            values[scene.time] = distanceBetweenTwoPoints(pwm.ballPositionX,
                                    pwm.ballPositionY, 0, -sConf.half_length);
                        }
                    }

                    if (mode == Mode_DistanceBallToGoalMonitor) {
                        values[scene.time] = distanceBetweenTwoPoints(scene.ball.pos.y,
                                scene.ball.pos.x, 0, -sConf.half_length);
                    }

                    if (mode == Mode_DistanceToEnemyMonitor) {
                        double shortestDistance = distanceBetweenTwoPoints(
                                scene.player[Register.getNumberOfPlayersLeftTeam()].pos.y,
                                scene.player[Register.getNumberOfPlayersLeftTeam()].pos.x,
                                scene.player[number - 1].pos.y,
                                scene.player[number - 1].pos.x);
                        for (int j = Register.getNumberOfPlayersLeftTeam(); j < scene.player.length; j++) {
                            if (distanceBetweenTwoPoints(scene.player[j].pos.y,
                                    scene.player[j].pos.x,
                                    scene.player[number - 1].pos.y,
                                    scene.player[number - 1].pos.x) < shortestDistance)
                                shortestDistance = distanceBetweenTwoPoints(
                                        scene.player[j].pos.y, scene.player[j].pos.x,
                                        scene.player[number - 1].pos.y,
                                        scene.player[number - 1].pos.x);
                        }
                        values[scene.time] = shortestDistance;
                    }

                    if (mode == Mode_DistanceToTeamMonitor) {
                        int index = 0;
                        if (number == 1)
                            index++;
                        double shortestDistance = distanceBetweenTwoPoints(
                                scene.player[index].pos.y, scene.player[index].pos.x,
                                scene.player[number - 1].pos.y,
                                scene.player[number - 1].pos.x);
                        for (int j = 1; j < Register.getNumberOfPlayersLeftTeam(); j++) {
                            if (j != number - 1) {
                                if (distanceBetweenTwoPoints(scene.player[j].pos.y,
                                        scene.player[j].pos.x,
                                        scene.player[number - 1].pos.y,
                                        scene.player[number - 1].pos.x) < shortestDistance)
                                    shortestDistance = distanceBetweenTwoPoints(
                                            scene.player[j].pos.y, scene.player[j].pos.x,
                                            scene.player[number - 1].pos.y,
                                            scene.player[number - 1].pos.x);
                            }
                        }
                        values[scene.time] = shortestDistance;
                    }

                    if (mode == Mode_BallSpeedTMinus1) {
                        // System.out.println("Ball Speed " +
                        // DaiWorldModelHistory.getCycle(scene.time).players[number-1].getBallSpeed()
                        // +
                        // " in Scene.Time/cycle " + scene.time + "/" +
                        // DaiWorldModelHistory.getCycle(scene.time).cycleNumber);
                        if (checkBallDistance(number, scene)) {

                            double actualSpeed = pwm.getBallSpeed();
                            if (actualSpeed != -9999 && actualSpeed != 0.0) {

                                double pastSpeed = 0;
                                int cyclesGone = 0;
                                for (int j = scene.time - 1; j > 0; j--) {
                                    cyclesGone++;
                                    PlayerWorldModel pwmOtherScene = WorldModel
                                            .getSceneSet().elementAt(j).player[number - 1]
                                            .getWorldModel();

                                    if (pwmOtherScene == null) {
                                        break;
                                    }
                                    pastSpeed = pwmOtherScene.getBallSpeed();
                                    if (pastSpeed != -9999)
                                        break;
                                }

                                if (pastSpeed != -9999) {
                                    System.out.println("Speed:       " + actualSpeed
                                            + " Cycle " + scene.time + " Old: "
                                            + pastSpeed);

                                    for (int j = 0; j < cyclesGone; j++) {
                                        pastSpeed = pastSpeed
                                                * SConf.getInstance().BALL_DECAY;
                                    }

                                    values[scene.time] = pastSpeed - actualSpeed;

                                    System.out.println("Old*Decay^" + cyclesGone + ": "
                                            + pastSpeed);
                                } else
                                    values[scene.time] = 0;
                            }
                        } else
                            values[scene.time] = gap_value;
                        ;
                    }

                    // check consistence
                    if (mode > 200 && mode != Mode_Holes) {
                        if (pwm == null 
                                || scene.time == values.length - 1
                                || scene.time == 0
                                || pwm.ballSpeedY == -9999 || pwm.ballSpeedX == -9999
                                || pwm.positionX == -9999 || pwm.positionY == -9999
                                || pwm.speedY == -9999 || pwm.speedX == -9999
                                || pwm.bodyAngle == -9999 || pwm.neckAngle == -9999
                                || pwm.ballInterceptX == -9999
                                || pwm.ballInterceptY == -9999
                                || pwm.ballPositionX == -9999
                                || pwm.ballPositionY == -9999 ) {
                            values[scene.time] = gap_value;
                        }
                    }

                    if (mode > 199 && mode != Mode_Holes)
                        // bei konst. Cycle (scene.time = konst.) ist das
                        // Verfahren, so wie es hier steht
                        // fehlerhaft. Deshalb werden hier alle konst. Cycle
                        // rausgefiltert (rw)
                        if (scene.time == lastSceneTime) {
                            values[scene.time] = gap_value;
                            values[scene.time - 1] = gap_value;
                        }
                }
            }
            lastSceneTime = scene.time;
        }
        if (mode == Mode_Holes) {
            PlayerWorldModel pwm = WorldModel.getSceneSet().elementAt(0).player[number - 1]
                                                                                .getWorldModel();
            if (pwm == null) {
                values[0] = 0;
            } else {
                values[0] = pwm.holes;
            }
            PlayerWorldModel opwm = WorldModel.getSceneSet().elementAt(values.length - 2).player[number - 1]
                                                                                             .getWorldModel();
            if (pwm == null) {
                values[values.length - 1] = 0;
            } else {
                values[values.length - 1] = opwm.holes;
            }
        }
        return values;
    }
    /**
     * is the distance to ball greater as in
     * StatisticDialog.getMaxDistanceTextField was enterd
     * 
     * @param int
     *            the player number the calculation depends on
     * @param the
     *            scene to analyse
     * @return boolean true or false
     */
    private static boolean checkBallDistance(int playerNumber, ClientScene scene) {
        PlayerWorldModel pwm = scene.player[playerNumber - 1].getWorldModel();
        if (pwm == null) {
            return false;
        }
        double playerBallDistance = pwm.getPlayerToBallDistance();
        if (playerBallDistance == -9999)
            return false;
        if (StatisticDialog.getMaxDistanceTextField() > playerBallDistance
                && StatisticDialog.getMinDistanceTextField() < playerBallDistance)
            return true;
        else
            return false;
    }

    /**
     * searches a scene with a player ball contact
     * 
     * @param int
     *            index of the first scene to analyse
     * @return int index of the scene with the next ball contact
     */
    private static int getIndexWithNextBallContact(int startIndex) {
        for (int i = startIndex; i < WorldModel.sceneSet.size() - 1; i++) {
            // System.out.println("getIndexWithNextBallContact for scene time =
            // " + i);
            if (wichPlayerHasBallAtSceneTime(i) > 0)
                return i;
        }
        return -1;
    }

    /**
     * looks whish player has the ball in a specific scene
     * 
     * @param int
     *            index of the scene to analyse
     * @return int the player number (player index)
     */
    private static int wichPlayerHasBallAtSceneTime(int sceneTime) {
        if (sceneTime < 0)
            return -1;

        int playerNumber = -1;

        double radius = sConf.CKICK_MARGIN + pConf.PLAYER_SIZE
                + SConf.getInstance().BALL_SIZE;

        ClientScene scene = new ClientScene();
        scene = WorldModel.sceneSet.elementAt(sceneTime);

        for (int j = 0; j < scene.player.length; j++) {

            // DEFINITION OF PASS SUCCESFUL OR NOT

            // System.out.println("wichPlayerHasBall for player = " + j+1);
            if ((scene.player[j].pos.x - scene.ball.pos.x) < radius
                    && (scene.player[j].pos.x - scene.ball.pos.x) > -radius
                    && (scene.player[j].pos.y - scene.ball.pos.y) < radius
                    && (scene.player[j].pos.y - scene.ball.pos.y) > -radius) {
                if (scene.player[j].isKicking()) {
                    // && scene.ball.acc.length() <
                    // nextScene.ball.acc.length()){

                    // System.out.println("matching wichPlayerHasBall with
                    // player = " + j+1);
                    if (playerNumber < 0)
                        playerNumber = j;
                    else {
                        if ((scene.player[j].pos.x - scene.ball.pos.x) < (scene.player[playerNumber].pos.x - scene.ball.pos.x))
                            System.out.println("change wichPlayerHasBall to player = "
                                    + (j + 1) + " from " + (playerNumber + 1));
                        playerNumber = j;
                    }
                }
            }
        }
        if (playerNumber > Register.getNumberOfPlayersLeftTeam())
            return scene.player[playerNumber].unum
                    + Register.getNumberOfPlayersLeftTeam();

        return playerNumber + 1; // +1 becouse playerNumber != index in
        // player[]
    }

    /**
     * calculates the distance between two points
     * 
     * @param double
     *            x1
     * @param double
     *            y1
     * @param double
     *            x2
     * @param double
     *            y2
     * @return double distance
     */
    private static double distanceBetweenTwoPoints(double x1, double y1, double x2,
            double y2) {
        double a = x1 - x2;
        double b = y1 - y2;
        return Math.sqrt(a * a + b * b);
    }

    /**
     * 
     * gets an array with the length of the actual cycle number
     * 
     * @param double[]
     */
    private static double[] getDoubleArrayWithActualCycleLength() {
        double[] array;
        try {
            array = new double
            // [Register.getPlayerBeanWithPlayerNumber(1).getMyFactBase().getVisualInfo().getCycle()];
            [AgentConnector.numberOfCycles() + 1];
        } catch (Exception e) {
            System.out.println("ERROR: " + e);
            array = new double[0];
        }
        return array;
    }

    /**
     * 
     * gets an array with the length of the actual cycle number an filled with
     * integers from 0 till actual cycle these are mostly the values for the
     * x-axis if the x-axis is shows the time
     * 
     * @param double[]
     */
    public static double[] getCycleArray() {
        double[] values = getDoubleArrayWithActualCycleLength();
        for (int i = 0; i < values.length; i++) {
            values[i] = i;
        }
        return values;
    }

    /**
     * 
     * calculates the average of a given double array
     * 
     * @param double[]
     *            values
     * @return double result
     */
    public static double calculateAverage(double[] values) {
        double result = 0;
        double help = 0;
        int real_length = 0;
        for (int i = 0; i < values.length; i++) {
            // don't consider gap values
            if (!(values[i] == gap_value)) {
                help = help + values[i];
                real_length++;
            }
        }
        // use default value if no values are given
        result = (real_length == 0) ? 0.1234567 : help / real_length;
        return result;
    }

    /**
     * 
     * calculates the varianz of a given double array using calculate average
     * 
     * @param double[]
     *            values
     * @return double result
     */
    public static double calculateVarianz(double[] values) {
        double d = 0;
        double a = calculateAverage(values);
        int real_length = 0;
        for (int i = 0; i < values.length; i++) {
            if (!(values[i] == gap_value)) {
                d = d + (values[i] - a) * (values[i] - a);
                real_length++;
            }
        }
        d = d / real_length;
        return d;
    }

    /**
     * 
     * calculates the standart deviation of a given double array using calculate
     * varianz
     * 
     * @param double[]
     *            values
     * @return double result
     */
    public static double calculateStandardDeviation(double[] values) {
        return Math.sqrt(calculateVarianz(values));
    }

    /**
     * 
     * counts the values != 0
     * 
     * @param double[]
     *            values
     * @return double result
     */
    public static double calculateFilledValues(double[] values) {
        double filled = 0;
        for (int i = 0; i < values.length; i++) {
            if (!(values[i] == gap_value))
                filled++;
        }
        return ((100 * filled) / values.length);
    }
}